package controllers;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.persistence.Cache;


import models.*;
import play.*;
import play.mvc.*;

@With(Secure.class)
public class Stages extends CRUD {

	/**
	 * Instancie des variables de session(session.put())
	 * Met ces variables dans des variables de rendu(render.args())
	 */
	@Before
	static void setConnectedUser() {
		if(Security.isConnected()) {
			if(!session.contains("agent_fullname")){
				Agent agent = Agent.find("nomUtilisateur", Security.connected()).first();
				Fonction gestFonct=Fonction.find("id_fonction like ?", "FONCT").first();
				Fonction gestTer=Fonction.find("id_fonction like ?", "TERRI").first();
				Fonction admin=Fonction.find("id_fonction like ?", "ADM").first();
				Fonction chef_CIS=Fonction.find("id_fonction like ?", "RCIS").first();
				Fonction formateur=Fonction.find("id_fonction like ?", "FOR").first();
				List<CIS> centres=CIS.find("responsable.id like ?", agent.id).fetch();
				boolean resp=!centres.isEmpty();
				/*
				 * Compte le nombre d'autorisation en attente pour les CIS où l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				List<Candidat> listeCandidats=new ArrayList<Candidat>();
				if(agent.fonction.contains(chef_CIS) || resp){
					Iterator<CIS> i=centres.iterator();
					while(i.hasNext()){
						List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", i.next().id, "AAUT").fetch();
						listeCandidats.addAll(cand);
					}
					session.put("nb_demande_auto", listeCandidats.size());
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
					long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
					session.put("nb_demande_valid_admin", nbValidAdmin);
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					session.put("nb_demande_annul_admin", nbAnnulAdmin);
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente pour le groupement dont l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(gestTer)){
					long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable like ? and demandeAnnulation is not true", "AVAL", agent);
					long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.id like ? and etatCandid.id_etatcandid not like ? or etatCandid.nom not like ?", agent.id, "ANN", "REF");
					session.put("nb_demande_valid_terri", nbValidTerri);
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					session.put("nb_demande_annul_terri", nbAnnulTerri);
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}

				/*
				 * Création des variables de session
				 */

				/*
				 * groupementResp_id représente l'id du groupement de l'agent si celui-ci est le responsable
				 * Sinon l'id du groupement auquel il appartient s'il possède la fonction gestionnaireTerritorial
				 */
				Groupement gpmt=Groupement.find("responsable like ?", agent).first();
				if(gpmt!=null){
					session.put("groupementResp_id", gpmt.id);
				}
				else if(agent.fonction.contains(gestTer)){
					session.put("groupementResp_id", agent.cis.groupement.id);
				}

				int aujourdhui=Calendar.getInstance().get(Calendar.YEAR);
				session.put("nomUtilisateur", agent.nomUtilisateur);
				session.put("anneeEnCours", aujourdhui);
				session.put("agent_id", agent.id);
				session.put("agent_niv", agent.niv.niv);
				session.put("agent_cis", agent.cis);
				session.put("agent_grpt", agent.cis.groupement);
				session.put("chef_CIS", agent.fonction.contains(chef_CIS));
				session.put("agent_email", agent.email);
				session.put("agent_fullname", agent.fullname());
				session.put("agent_responsable", resp);
				session.put("agent_grade", agent.grade.toString());
				session.put("gestionnaireFonct", (agent.fonction.contains(gestFonct)));
				session.put("gestionnaireTerri", agent.fonction.contains(gestTer));
				session.put("formateur", agent.fonction.contains(formateur));
				session.put("admin", agent.fonction.contains(admin));
				session.put("CISService", agent.cis.nom);
				/*
				 * Compte le nombre de validations en attente pour les fmpa et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=FMPA.count("etat.nom like ?", "Attente de validation");
					session.put("nb_valid_fmpa", nbValidAdmin);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(gestTer)){
					long nbValidTerri=FMPA.count("etat.nom like ? and cis.groupement.nom like ?", "Attente de validation", session.get("agent_grpt"));
					session.put("nb_valid_fmpa", nbValidTerri);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(chef_CIS) || resp){
					long nbValidCis=FMPA.count("etat.nom like ? and cis.nom like ?", "Attente de validation", session.get("CISService"));
					session.put("nb_valid_fmpa", nbValidCis);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				System.out.println(session.get("nb_valid_fmpa"));
				/*
				 * Création des variables de rendu
				 */
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				if(agent.niv.id != 0){
					session.put("agent_for", agent.niv);
					renderArgs.put("agent_for", session.get("agent_for"));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
			else{
				/*
				 * Création des variables de rendu si les variables de session existent
				 */
				if(session.contains("nb_demande_valid_terri") || session.contains("nb_demande_annul_terri")){
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				if(session.contains("nb_demande_valid_admin") || session.contains("nb_demande_annul_admin")){
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				renderArgs.put("agent_for", session.get("agent_for"));
				if(session.contains("nb_valid_fmpa")){
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
		}
	}

	/**
	 * Affiche le formulaire de création de stage
	 */
	public static void newStageForm(){
		if (!session.get("admin").equals("true")){
			render("@accessDenied");
		}
		//Récupère les informations à afficher dans les menus déroulants dans la base de données
		else{
			List<Nature> natures = Nature.findAll();
			List<Groupement> structures = Groupement.findAll();
			List<EtatStage> etats=EtatStage.findAll();
			List<Intitule> intitules=Intitule.findAll();
			List<CIS> ciss = CIS.find("order by nom").fetch();
			List<DureeStage> durees=DureeStage.findAll();
			render(natures, etats, intitules, ciss, structures, durees);
		}
	}


	/**
	 * Enregistre le nouveau stage dans la base de données
	 * @param code
	 * @param intitule
	 * @param nature
	 * @param groupement
	 * @param effectifMin
	 * @param effectifMax
	 * @param modalites
	 * @param cis
	 * @param description
	 * @param duree
	 * @param dateDeb
	 * @param dateFin
	 * @param dateExam
	 */
	public static void newStageSave(String code, long intitule, long nature, long groupement, int effectifMin, 
			int effectifMax, String modalites, long cis, String description, long duree, 
			Date dateDeb, Date dateFin, Date dateExam){
		if (session.get("admin").equals("false")){
			render("@accessDenied");
		}
		else{
			EtatStage etat=EtatStage.find("id_etatstage like ?", "ATT").first();
			Nature natureObj=Nature.findById(nature);
			Groupement structureObj=Groupement.findById(groupement);
			Intitule intituleObj=Intitule.findById(intitule);
			CIS cisObj=null;
			if(cis!=0){
				cisObj=CIS.findById(cis);
			}
			DureeStage dureeObj=DureeStage.findById(duree);
			//Récupère les informations des différents éléments à afficher dans les listes déroulantes

			Stage stage;
			if(dateExam==null){
				stage=new Stage(code, intituleObj, natureObj, structureObj, effectifMin, effectifMax, modalites, description, etat,dureeObj, dateDeb, dateFin, dateFin, null, null, cisObj);
			}
			else{
				stage=new Stage(code, intituleObj, natureObj, structureObj, effectifMin, effectifMax, modalites, description, etat,dureeObj, dateDeb, dateFin, dateExam, null, null, cisObj);
			}
			//Vérification des dates et changement du format pour pré-remplissage en cas d'erreur 
			if(dateFin !=null && dateFin.before(dateDeb)){
				List<Agent> agents = Agent.all().fetch();
				List<Nature> natures = Nature.all().fetch();
				List<EtatStage> etats=EtatStage.all().fetch();
				List<Intitule> intitules=Intitule.all().fetch();
				List<Groupement> structures = Groupement.findAll();
				List<CIS> ciss = CIS.all().fetch();
				List<DureeStage> durees=DureeStage.findAll();

				flash.error("La date de fin du stage n'est pas valide, elle doit être postérieur à la date de début");
				render("@newStageForm", stage, agents, natures, etats, intitules, ciss, structures, durees);
			}
			else{
				validation.valid(stage);
				//Si le formulaire n'a pas été rempli correctement, affichage d'un bandeau d'erreur et 
				//préremplissage du formulaire avec les données précédemment rentrées
				if(validation.hasErrors() || effectifMax==0 || effectifMin==0){
					List<Agent> agents = Agent.all().fetch();
					List<Nature> natures = Nature.all().fetch();
					List<EtatStage> etats=EtatStage.all().fetch();
					List<Intitule> intitules=Intitule.all().fetch();
					List<Groupement> structures = Groupement.findAll();
					List<CIS> ciss = CIS.all().fetch();
					List<DureeStage> durees=DureeStage.findAll();
					flash.error("Il y a une erreur dans le formulaire");
					render("@newStageForm", stage, agents, natures, etats, intitules, ciss, structures, durees);
				}
				//Si le formulaire et correctement rempli, enregistrement du stage dans le base de données,
				//affichage d'un bandeau de confirmation de création de stage et redirection vers le formulaire de création
				else{
					stage.save();
					flash.success("Le stage a bien été enregistré.");
					newStageForm();
				}
			}
		}
	}


	/**
	 * Affiche le formulaire de modification du stage d'id stageId pour les admins
	 * @param stageId
	 */
	public static void modifStageAdmin(long stageId){
		List<Nature> natures = Nature.findAll();
		List<Groupement> structures = Groupement.findAll();
		List<EtatStage> etats=EtatStage.findAll();
		List<Intitule> intitules=Intitule.findAll();
		List<CIS> ciss = CIS.findAll();
		List<DureeStage> durees=DureeStage.findAll();
		Stage stage=Stage.findById(stageId);
		render(stage, natures, structures, etats, intitules, ciss, durees);

	}

	/**
	 * Affiche le formulaire de modification de stage pour le gestionnaire administratif
	 * @param idStage
	 */
	public static void modifStageForm(long idStage){
		Agent agent = Agent.findById(Long.decode(session.get("agent_id")));
		String dateExam=null;
		String dateFin=null;
		String dateDeb=null;
		Stage stage=Stage.findById(idStage);
		boolean isTerri=session.get("gestionnaireTerri").equals("true") && stage.structure.id==Long.decode(session.get("groupementResp_id"));
		//Vérification des droits de l'agent connecté
		//Si l'agent ne possède pas les droits suffisants il est redirigé vers la page accessDenied.html
		if (!isTerri ){
			render("@accessDenied");
		}
		else{
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			if(stage.dateDeb!=null){
				dateDeb=sdf.format(stage.dateDeb);
			}
			if(stage.dateFin!=null){
				dateFin=sdf.format(stage.dateFin);
			}
			if(stage.dateExam!= null){
				dateExam=sdf.format(stage.dateExam);
			}
			render(stage, agent, dateDeb, dateFin, dateExam, idStage);
		}
	}

	/**
	 * Affiche les stages terminés ou réalisés
	 */
	public static void gererStagesTermine(){
		if (!session.get("admin").equals("true") && !session.get("gestionnaireFonct").equals("true")){
			render("@accessDenied");
		}
		else{
			//selection des stages terminés ou réalisés.
			List<Stage> stages=Stage.find("etat.id_etatstage like ? or etat.id_etatstage like ? or etat.id_etatstage like ? or etat.id_etatstage like ? or etat.id_etatstage like ?","TER","REA","REAI","REACE", "ANN").fetch();
			render(stages);
		}
	}

	/**
	 * Affiche le formulaire d'ajout des dates administratives pour le stage d'id "stageId"
	 * @param stageId
	 */
	public static void ajouterDatesAdministratives(long stageId){
		if (!session.get("admin").equals("true") && !session.get("gestionnaireFonct").equals("true")){
			render("@accessDenied");
		}
		else{
			render(stageId);
		}
	}

	/**
	 * Sauve les dates administratives et change l'état du stage
	 * @param dateFinan
	 * @param dateComp
	 * @param stageId
	 */
	public static void ajouterDatesAdministrativesSave(Date dateFinan, Date dateComp, long stageId){
		if (!session.get("admin").equals("true") && !session.get("gestionnaireFonct").equals("true")){
			render("@accessDenied");
		}
		else{
			Stage stage=Stage.findById(stageId);
			EtatStage termine=EtatStage.find("id_etatstage like ?", "TER").first();
			EtatStage realiseFinan=EtatStage.find("id_etatstage like ?", "REAI").first();
			EtatStage realiseComp=EtatStage.find("id_etatstage like ?", "REAEC").first();
			if(dateFinan!=null && dateComp!=null){
				stage.dateFinancier=dateFinan;
				stage.datePedagogique=dateComp;
				stage.etat=termine;
			}
			else if(dateFinan!=null){
				stage.dateFinancier=dateFinan;
				stage.etat=realiseFinan;
			}
			else if(dateComp!=null){
				stage.datePedagogique=dateComp;
				stage.etat=realiseComp;
			}
			flash.success("Les dates ont bien été enregistrées.");
			stage.save();
			gererStagesTermine();
		}
	}

	public static void modifStageAdminSave(String code, long intitule, long nature, long groupement, int effectifMin, 
			int effectifMax, String modalites, long cis, String description, long duree, 
			Date dateDeb, Date dateFin, Date dateExam, long stageId){
		System.out.println(session.get("admin"));
		if (!session.get("admin").equals("true") && !session.get("gestionnaireFonct").equals("true")){
			render("@accessDenied");
		}
		else{
			EtatStage etat=EtatStage.find("id_etatstage like ?", "ATT").first();
			Nature natureObj=Nature.findById(nature);
			Groupement structureObj=Groupement.findById(groupement);
			Intitule intituleObj=Intitule.findById(intitule);
			CIS cisObj=null;
			if(cis!=0){
				cisObj=CIS.findById(cis);
			}
			DureeStage dureeObj=DureeStage.findById(duree);
			//Récupère les informations des différents éléments à afficher dans les listes déroulantes

			Stage stage=Stage.findById(stageId);
			if(dateExam==null){
				stage.code=code;
				stage.intitule=intituleObj;
				stage.nature=natureObj;
				stage.structure=structureObj;
				stage.effectifMax=effectifMax;
				stage.effectifMin=effectifMin;
				stage.modalites=modalites;
				stage.description=description;
				stage.etat=etat;
				stage.duree=dureeObj;
				stage.dateDeb=dateDeb;
				stage.dateFin=dateFin;
				stage.dateExam=dateFin;
				stage.cis=cisObj;
			}
			else{
				stage.code=code;
				stage.intitule=intituleObj;
				stage.nature=natureObj;
				stage.structure=structureObj;
				stage.effectifMax=effectifMax;
				stage.effectifMin=effectifMin;
				stage.modalites=modalites;
				stage.description=description;
				stage.etat=etat;
				stage.duree=dureeObj;
				stage.dateDeb=dateDeb;
				stage.dateFin=dateFin;
				stage.dateExam=dateExam;
				stage.cis=cisObj;
			}
			//Vérification des dates et changement du format pour pré-remplissage en cas d'erreur 
			if(dateFin !=null && dateFin.before(dateDeb)){
				List<Agent> agents = Agent.all().fetch();
				List<Nature> natures = Nature.all().fetch();
				List<EtatStage> etats=EtatStage.all().fetch();
				List<Intitule> intitules=Intitule.all().fetch();
				List<Groupement> structures = Groupement.findAll();
				List<CIS> ciss = CIS.all().fetch();
				List<DureeStage> durees=DureeStage.findAll();

				flash.error("La date de fin du stage n'est pas valide, elle doit être postérieur à la date de début");
				render("@modifStageAdmin", stage, agents, natures, etats, intitules, ciss, structures, durees);
			}
			else{
				validation.valid(stage);
				//Si le formulaire n'a pas été rempli correctement, affichage d'un bandeau d'erreur et 
				//préremplissage du formulaire avec les données précédemment rentrées
				if(validation.hasErrors() || effectifMax==0 || effectifMin==0){
					List<Agent> agents = Agent.all().fetch();
					List<Nature> natures = Nature.all().fetch();
					List<EtatStage> etats=EtatStage.all().fetch();
					List<Intitule> intitules=Intitule.all().fetch();
					List<Groupement> structures = Groupement.findAll();
					List<CIS> ciss = CIS.all().fetch();
					List<DureeStage> durees=DureeStage.findAll();
					flash.error("Il y a une erreur dans le formulaire");
					render("@modifStageAdmin", stage, agents, natures, etats, intitules, ciss, structures, durees);
				}
				//Si le formulaire et correctement rempli, enregistrement du stage dans le base de données,
				//affichage d'un bandeau de confirmation de création de stage et redirection vers le formulaire de création
				else{
					stage.save();
					flash.success("Le stage a bien été enregistré.");
					modifStageAdmin(stageId);
				}
			}
		}
	}


	/**
	 * Sauvegarde les modifications apportées au stage
	 * @param dateDeb
	 * @param dateFin
	 * @param dateExam
	 * @param idStage
	 */
	public static void modifStage(Date dateDeb, Date dateFin, Date dateExam, long idStage){
		//Vérification des droits de l'agent connecté
		//Si l'agent ne possède pas les droits suffisants il est redirigé vers la page accessDenied.html
		if (!session.get("admin").equals("true") && !session.get("gestionnaireFonct").equals("true") && !session.get("gestionnaireTerri").equals("true")){
			render("@accessDenied");
		}
		else{
			Stage stage=Stage.findById(idStage);
			if(dateFin==null || dateDeb==null){
				flash.error("La date de début ou la date de fin est n'a pas été renseigné");
				modifStageForm(idStage);
			}
			else if(dateFin.before(dateDeb)){
				flash.error("La date de fin ne peut pas être antérieur à la date de début");
				modifStageForm(idStage);
			}
			else if(dateFin!=null){
				stage.dateDeb=dateDeb;
				stage.dateFin=dateFin;
				if(dateExam==null ||dateExam.before(dateFin) || dateExam.equals(dateFin)){
					stage.dateExam=dateFin;
					flash.success("Le stage a bien été modifié, la date d'examen a été mise à la date de fin");
				}
				else{
					stage.dateExam=dateExam;
					flash.success("Le stage a bien été modifié");
				}
			}
			stage.save();
			modifStageForm(idStage);
		}
	}


	/**
	 * Formulaire d'ajout des responsables pour le stage d'id "idStage"
	 * @param idStage
	 */
	public static void ajouterResponsablesForm(long idStage){
		Stage stage=Stage.findById(idStage);
		boolean isTerri=session.get("gestionnaireTerri").equals("true") && stage.structure.id==Long.decode(session.get("groupementResp_id"));
		//Vérification des droits de l'agent connecté
		//Si l'agent ne possède pas les droits suffisants il est redirigé vers la page accessDenied.html
		if (session.get("admin").equals("false") && session.get("gestionnaireFonct").equals("false") && !isTerri ){
			render("@accessDenied");
		}
		//Affiche le formulaire de saisie de responsables
		else{
			List<Agent> agents=Agent.find("order by nom").fetch();
			List<Agent> respPedago=agents;
			Fonction fonction=Fonction.find("id_fonction like ?", "TERRI").first();
			Iterator<Agent> it=agents.iterator();
			List<Agent> respAdmin=new ArrayList<Agent>();
			while(it.hasNext()){
				Agent a=it.next();
				if(a.fonction.contains(fonction)){
					respAdmin.add(a);
				}
			}
			render(stage, respPedago, respAdmin);
		}
	}

	/**
	 * Sauvegarde les responsables pour le stage d'id "idStage"
	 * @param respPedag
	 * @param gestAdmin
	 * @param idStage
	 */
	public static void ajouterResponsables(long respPedag, long gestAdmin, long idStage){
		Stage stage=Stage.findById(idStage);
		//Vérification des droits de l'agent connecté
		//Si l'agent ne possède pas les droits suffisants il est redirigé vers la page accessDenied.html
		if (session.get("admin").equals("false") && session.get("gestionnaireFonct").equals("false") && (session.get("gestionnaireTerri").equals("false") && stage.structure.id.equals(Long.decode(session.get("responsable_id"))))){
			render("@accessDenied");
		}
		//Récupère le responsable pédagogique et le gestionnaire administratif du formulaire
		//du stage et enregistre le stage modifié
		else{
			if(respPedag!=0){
				stage.directeur=Agent.findById(respPedag);
			}
			if(gestAdmin!=0){
				stage.gestionnaireAdmin=Agent.findById(gestAdmin);
			}
			flash.success("Le(s) responsable(s) a (ont) bien été ajouté(s) au stage.");
			stage.save();
			detailStage(idStage);
		}
	}


	/**
	 * Annule le stage et les candidatures associées
	 * @param stageId
	 */
	public static void annulerStage(long stageId){
		if(session.get("gestionnaireTerri").equals("true")){
			Stage stage=Stage.findById(stageId);
			if(stage.structure.id.equals(Long.decode(session.get("groupementResp_id")))){
				EtatStage etatAnnule=EtatStage.find("id_etatstage like ?", "ANN").first();
				stage.etat=etatAnnule;
				Iterator<Candidat> i=stage.candidatures.iterator();
				EtatCandid candidAnnule=EtatCandid.find("id_etatcandid like ?", "ANN").first();
				while(i.hasNext()){
					Candidat candid=i.next();
					if(candid.etatCandid.id_etatcandid.equals("VAL") || candid.etatCandid.id_etatcandid.equals("AAUT") || candid.etatCandid.id_etatcandid.equals("AVAL") || candid.etatCandid.id_etatcandid.equals("LA")){
						candid.etatCandid=candidAnnule;
						candid.motifAnnulation=MotifAnnulation.find("code like ?", "SA").first();
					}
					stage.save();
					candid.save();
				}
				detailStage(stageId);
			}
			else{
				render("@accessDenied");
			}
		}
		else if(session.get("gestionnaireFonct").equals("true") || session.get("admin").equals("true")){
			Stage stage=Stage.findById(stageId);
			EtatStage etatAnnule=EtatStage.find("id_etatstage like ?", "ANN").first();
			stage.etat=etatAnnule;
			Iterator<Candidat> i=stage.candidatures.iterator();
			EtatCandid candidAnnule=EtatCandid.find("id_etatcandid like ?", "ANN").first();
			while(i.hasNext()){
				Candidat candid=i.next();
				if(candid.etatCandid.id_etatcandid.equals("VAL") || candid.etatCandid.id_etatcandid.equals("AAUT") || candid.etatCandid.id_etatcandid.equals("AVAL") || candid.etatCandid.id_etatcandid.equals("LA")){
					candid.etatCandid=candidAnnule;
					candid.motifAnnulation=MotifAnnulation.find("id_motifannulation like ?", "SA").first();
				}
				candid.save();
			}
			stage.save();
			detailStage(stageId);
		}
		else{
			render("@accessDenied");
		}
	}


	/**
	 * Cloture les candidatures du stage d'id "stageId"
	 * @param stageId
	 */
	public static void cloturerCandidatures(long stageId){
		Stage stage=Stage.findById(stageId);
		boolean isTerri=session.get("gestionnaireTerri").equals("true") && stage.structure.id==Long.decode(session.get("groupementResp_id"));
		//Vérification des droits de l'agent connecté
		//Si l'agent ne possède pas les droits suffisants il est redirigé vers la page accessDenied.html
		if (session.get("admin").equals("false") && session.get("gestionnaireFonct").equals("false") && !isTerri ){
			render("@accessDenied");
		}
		else{
			EtatStage etat=EtatStage.find("id_etatstage like ?", "CANCLO").first();
			stage.etat=etat;
			stage.save();
			detailStage(stageId);
		}
	}


	/**
	 * Ouvre les candidatures du stage d'id "stageId"
	 * @param stageId
	 */
	public static void ouvrirCandidatures(long stageId){
		Stage stage=Stage.findById(stageId);
		EtatStage etat=EtatStage.find("id_etatstage like ?", "ATT").first();
		stage.etat=etat;
		stage.save();
		detailStage(stageId);
	}

	/**
	 * Génère la liste des candidature du stage d'id "id"
	 * @param id
	 * id du stage dans la base de données
	 */
	public static void listCandid(long id){
		Stage stage = (Stage) Stage.findById(id);
		List<Candidat> candids=stage.getCandidatures();
		render(candids,stage);
	}

	public static void validerCompetences(long id){
		Stage stage=Stage.findById(id);
		List<Candidat> candids=stage.getCandidatures();
		List<Candidat> listeARender=new ArrayList<Candidat>();
		Iterator<Candidat> it=candids.iterator();
		Candidat tempCandid;

		//parcours des candidats du stage afin de n'afficher que les stagiaires.
		while (it.hasNext()){
			tempCandid=it.next();
			if(tempCandid.role.toString().equals("Stagiaire")){
				listeARender.add(tempCandid);
			}
		}
		render(listeARender);
	}

	public static void bilanPedago(long id){
		Stage stage=Stage.findById(id);
		List<Candidat> candids=stage.getCandidatures();
		List<Candidat> listeARender=new ArrayList<Candidat>();
		Iterator<Candidat> it=candids.iterator();
		Candidat tempCandid;

		//parcours des candidats du stage afin de n'afficher que les stagiaires.
		while (it.hasNext()){
			tempCandid=it.next();
			if(tempCandid.role.toString().equals("Stagiaire")){
				listeARender.add(tempCandid);
			}
		}
		render(listeARender);
	}


	/**
	 * Affiche la liste des stages en attente
	 * @param id
	 */
	public static void listStages(int id){

		List<Stage> stages; 
		Date aujourdhui = new Date();
		boolean isStage=true;
		//recuperation de la date du jour
		Calendar cal = Calendar.getInstance();
		//specification du format de sortie a utilise (celui reconnut par SQL)
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		//permet de n'afficher que les stages non passés
		if(id == 0)
		{
			//utilisation de la methode find() de play.
			//on convertit la date actuelle fournit par Calendar en utilisant le SimpleDateFormat creer
			//specification de date, dateDeb doit etre superieur a la date actuel et non nul.
			stages=Stage.find("(dateDeb is null) or (etat.id_etatstage not like ? and etat.id_etatstage not like ? and etat.id_etatstage not like ? and etat.id_etatstage not like ? and etat.id_etatstage not like ?) order by intitule, dateDeb", "TER", "ANN", "REA", "REAI", "REACE" ).fetch();
			isStage=(stages.size()!=0);
		}
		//Affiche les stages passés
		else {
			stages=Stage.find("etat.id_etatstage like ?", "TER").fetch();
			isStage=(stages.size()!=0);
		}
		render(stages, aujourdhui, isStage);
	}

	/**
	 * Affiche le détail du stage d'id "id"
	 * @param id
	 * id du stage
	 */
	public static void detailStage(long id){		
		Stage stage = Stage.findById(id);
		//Candidature validée
		List<Uv> uVs= stage.intitule.uVs;
		List<Candidat> candidats = Candidat.find("stage like ? and etatCandid.id_etatcandid not like ? and etatCandid.id_etatcandid not like ? and etatCandid.id_etatcandid not like ?)", stage, "AAUT", "AVAL", "NAUT").fetch();
		// List<Candidat> candidats = stage.getCandidatures();
		Date aujourdhui = new Date();
		render(stage, candidats, aujourdhui, uVs);	

	}

	/**
	 * Enregistre la candidature de l'agent pour le stage d'id "idStage"
	 * @param idStage
	 * @param logement
	 * @param motivation
	 * @param role
	 * @param precisionDate
	 * @param candidPartielle
	 */
	public static void deposerCandidature(long idStage, boolean logement, String motivation, long role, String precisionDate, boolean candidPartielle){	
		Agent agent = Agent.findById(Long.decode(session.get("agent_id")));
		Stage stage = (Stage) Stage.findById(idStage);
		List<Uv> uvs=stage.intitule.uVs;
		Iterator<Uv> i=uvs.iterator();
		Candidat c = new Candidat(agent, stage, motivation, role, null);
		if(stage.etat.id_etatstage.equals("ANN")){
			flash.error("Vous ne pouvez pas candidater sur un stage annulé");
			detailStage(stage.id);
		}
		else if(stage.etat.id_etatstage.equals("CANCLO")){
			flash.error("Les candidatures de ce stage sont clôturées");
			detailStage(stage.id);
		}
		else if(stage.etat.id_etatstage.equals("REA") || stage.etat.id_etatstage.equals("REAI") || stage.etat.id_etatstage.equals("REACE") || stage.etat.id_etatstage.equals("TER")){
			flash.error("Ce stage est terminé");
			detailStage(stage.id);
		}
		else if(role != 0)
		{
			if(!motivation.equals("")){
				if(!stage.contientCandidat(c)){
					while(i.hasNext()){
						Uv uv=i.next();
						if(params.get(uv.nom)!=null){
							c.examenUv.add(uv);
						}
					}
					c.candidater(logement, role, precisionDate, candidPartielle);
					agent.save();
					stage.save();
					flash.success("Votre candidature a bien été enregistrée");
					detailStage(stage.id);
				}
				else {
					Role roles = Role.findById(role);
					flash.error("Vous ne pouvez pas candidater en tant que "+roles.toString()+" pour ce stage");
					candidStage(stage.id);
				}
			}
			else {
				flash.error("Vous devez remplir le champ motivation");
				candidStage(stage.id);
			}
		}
		else {
			flash.error("Vous devez choisir un rôle pour ce stage");
			candidStage(stage.id);
		}
	}

	/**
	 * Affiche le formulaire de candidature pour le stage d'id "id"
	 * @param id
	 */
	public static void candidStage(long id)
	{
		Stage stage = Stage.findById(id);
		List<Role> roles = Role.all().fetch();
		render(stage, roles);

	}


	public static void statistiques(){
		List<Intitule> intitules=Intitule.findAll();
		List<Role> roles=Role.findAll(); 
		render(intitules, roles);
	}

	public static void statistiquesAnneePrec(){
		List<Intitule> intitules=Intitule.findAll();
		List<Role> roles=Role.findAll(); 
		render(intitules, roles);
	}


	/**
	 * Calcule les statistiques des stages de l'année en cours
	 * @param intitule
	 * @param role
	 */
	public static void afficherStatistiques(long intitule, long role){
		int aujourdhui=Calendar.getInstance().get(Calendar.YEAR);
		List<Stage> stages;
		List<StatistiquesStage> statStages=new ArrayList<StatistiquesStage>();
		StatistiquesStage stat=new StatistiquesStage();
		float nbjoursTotal=0;
		float nbjours=0;
		int nbParticipantsTotal=0;
		int nbParticipant=0;
		Intitule intit=Intitule.findById(intitule);
		Role roleObj=Role.findById(role);
		if(intitule==0){
			stages=Stage.find("year(dateDeb) like ?", aujourdhui).fetch();
			Iterator<Stage> i=stages.iterator();
			if(role==0){
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					nbParticipantsTotal+=stage.candidatures.size();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						Candidat cand=iCand.next();
						if(cand.examenUv.size()==0){
							nbjours+=stage.duree.jours;
							nbjoursTotal+=stage.duree.jours;
						}
						else{
							Iterator<Uv> iUv=cand.examenUv.iterator();
							while(iUv.hasNext()){
								Uv uv=iUv.next();
								nbjours+=uv.dureeEpreuve;
								nbjoursTotal+=uv.dureeEpreuve;
							}
						}
						nbParticipant++;
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
			else{
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						Candidat cand=iCand.next();
						if(cand.role.equals(roleObj)){
							nbParticipantsTotal++;
							nbParticipant++;
							if(cand.examenUv.size()==0){
								nbjours+=stage.duree.jours;
								nbjoursTotal+=stage.duree.jours;
							}
							else{
								Iterator<Uv> iUv=cand.examenUv.iterator();
								while(iUv.hasNext()){
									Uv uv=iUv.next();
									nbjours+=uv.dureeEpreuve;
									nbjoursTotal+=uv.dureeEpreuve;
								}
							}
						}
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
		}
		else{
			stages=Stage.find("intitule like ? and year(dateDeb) like ?", intit, aujourdhui).fetch();
			Iterator<Stage> i=stages.iterator();
			if(role==0){
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						nbParticipantsTotal++;
						nbParticipant++;
						Candidat cand=iCand.next();
						if(cand.examenUv.size()==0){
							nbjours+=stage.duree.jours;
							nbjoursTotal+=stage.duree.jours;
						}
						else{
							Iterator<Uv> iUv=cand.examenUv.iterator();
							while(iUv.hasNext()){
								Uv uv=iUv.next();
								nbjours+=uv.dureeEpreuve;
								nbjoursTotal+=uv.dureeEpreuve;
							}
						}
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
			else{
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						Candidat cand=iCand.next();
						if(cand.role.equals(roleObj)){
							nbParticipantsTotal++;
							nbParticipant++;
							if(cand.examenUv.size()==0){
								nbjours+=stage.duree.jours;
								nbjoursTotal+=stage.duree.jours;
							}
							else{
								Iterator<Uv> iUv=cand.examenUv.iterator();
								while(iUv.hasNext()){
									Uv uv=iUv.next();
									nbjours+=uv.dureeEpreuve;
									nbjoursTotal+=uv.dureeEpreuve;
								}
							}
						}
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
		}
		render(statStages, roleObj, intit, nbParticipantsTotal, nbjoursTotal);
	}


	/**
	 * Calcule les statistiques de l'année précédente
	 * @param intitule
	 * @param role
	 */
	public static void afficherStatistiquesAnneePrec(long intitule, long role){
		int anneePrec=Calendar.getInstance().get(Calendar.YEAR)-1;
		List<Stage> stages;
		List<StatistiquesStage> statStages=new ArrayList<StatistiquesStage>();
		StatistiquesStage stat=new StatistiquesStage();
		float nbjoursTotal=0;
		float nbjours=0;
		int nbParticipantsTotal=0;
		int nbParticipant=0;
		Intitule intit=Intitule.findById(intitule);
		Role roleObj=Role.findById(role);
		if(intitule==0){
			stages=Stage.find("year(dateDeb) like ?", anneePrec).fetch();
			Iterator<Stage> i=stages.iterator();
			if(role==0){
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					nbParticipantsTotal+=stage.candidatures.size();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						Candidat cand=iCand.next();
						if(cand.examenUv.size()==0){
							nbjours+=stage.duree.jours;
							nbjoursTotal+=stage.duree.jours;
						}
						else{
							Iterator<Uv> iUv=cand.examenUv.iterator();
							while(iUv.hasNext()){
								Uv uv=iUv.next();
								nbjours+=uv.dureeEpreuve;
								nbjoursTotal+=uv.dureeEpreuve;
							}
						}
						nbParticipant++;
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
			else{
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						Candidat cand=iCand.next();
						if(cand.role.equals(roleObj)){
							nbParticipantsTotal++;
							nbParticipant++;
							if(cand.examenUv.size()==0){
								nbjours+=stage.duree.jours;
								nbjoursTotal+=stage.duree.jours;
							}
							else{
								Iterator<Uv> iUv=cand.examenUv.iterator();
								while(iUv.hasNext()){
									Uv uv=iUv.next();
									nbjours+=uv.dureeEpreuve;
									nbjoursTotal+=uv.dureeEpreuve;
								}
							}
						}
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
		}
		else{
			stages=Stage.find("intitule like ? and year(dateDeb) like ?", intit, anneePrec).fetch();
			Iterator<Stage> i=stages.iterator();
			if(role==0){
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						nbParticipantsTotal++;
						nbParticipant++;
						Candidat cand=iCand.next();
						if(cand.examenUv.size()==0){
							nbjours+=stage.duree.jours;
							nbjoursTotal+=stage.duree.jours;
						}
						else{
							Iterator<Uv> iUv=cand.examenUv.iterator();
							while(iUv.hasNext()){
								Uv uv=iUv.next();
								nbjours+=uv.dureeEpreuve;
								nbjoursTotal+=uv.dureeEpreuve;
							}
						}
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
			else{
				Iterator<Candidat> iCand;
				while(i.hasNext()){
					Stage stage=i.next();
					iCand=stage.candidatures.iterator();
					while(iCand.hasNext()){
						Candidat cand=iCand.next();
						if(cand.role.equals(roleObj)){
							nbParticipantsTotal++;
							nbParticipant++;
							if(cand.examenUv.size()==0){
								nbjours+=stage.duree.jours;
								nbjoursTotal+=stage.duree.jours;
							}
							else{
								Iterator<Uv> iUv=cand.examenUv.iterator();
								while(iUv.hasNext()){
									Uv uv=iUv.next();
									nbjours+=uv.dureeEpreuve;
									nbjoursTotal+=uv.dureeEpreuve;
								}
							}
						}
					}
					stat.code=stage.code;
					stat.dateDeb=stage.dateDeb;
					stat.intitule=stage.intitule;
					stat.nbAgents=nbParticipant;
					stat.nbjours=nbjours;
					statStages.add(stat);
					stat=new StatistiquesStage();
					nbjours=0;
					nbParticipant=0;
				}
			}
		}
		render(statStages, roleObj, intit, nbParticipantsTotal, nbjoursTotal);
	}


	/**
	 * Affiche la liste des staigiaires dans un format imprimable
	 * @param idStage
	 */
	public static void imprimeListe(long idStage){
		Stage stage=Stage.findById(idStage);
		List<Candidat> stagiaires=Candidat.find("stage.id like ? and etatCandid.id_etatcandid like ? and role.id_role like ?", idStage, "VAL", "STAG").fetch();
		render(stage, stagiaires);
	}
}